﻿using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net.Sockets;
using System.Runtime.Serialization.Formatters.Binary;
using System.Text;
using System.Threading.Tasks;
using WebSocketChat.Common.Database;

namespace WebSocketChat.Common
{
    public class SocketUser
    {
        public ChatUser User { get; set; }
        public Socket Socket { get; set; }
    }

    public class WebSocketUser
    {
        public ChatUser User { get; set; }
        public SuperSocket.WebSocket.WebSocketSession Session { get; set; }
    }

    public class ChatGroup
    {
        public FriendGroups Group { get; set; }
        public List<ChatFriend> Users { get; set; }
    }

    public class ChatFriend
    {
        public string NickName { get; set; }
        public ChatUser User { get; set; }
    }

    public interface IMessage
    {
        /// <summary>
        /// 发送者ID
        /// </summary>
        int Sender { get; set; }
        /// <summary>
        /// 接收者ID
        /// </summary>
        int Receiver { get; set; }
        /// <summary>
        /// 指令类型，如消息、离在线、广播等
        /// </summary>
        MessageType Type { get; set; }
        /// <summary>
        /// 消息内容类型，如图片、文本
        /// </summary>
        ContentType Ctype { get; set; }
        /// <summary>
        /// 状态
        /// </summary>
        int Status { get; set; }
        /// <summary>
        /// 数据，二进制对象或json
        /// </summary>
        object Data { get; set; }
        /// <summary>
        /// CommandMessage和ChatMessage之间的相互转换
        /// </summary>
        /// <returns></returns>
        IMessage ChangeMsg();
        /// <summary>
        /// 序列化二进制
        /// </summary>
        /// <param name="tag">0CommandMessage 1ChatMessage</param>
        /// <returns></returns>
        byte[] Serialize(bool tag = true);
        /// <summary>
        /// 序列化为json
        /// </summary>
        /// <returns></returns>
        string SerializeJson();
    }

    public class MessageConvert
    {
        public static IMessage Parse(byte[] bytes, int count)
        {
            byte[] byt = bytes.Skip(1).Take(count).ToArray();
            if (bytes[0] == 0)//CommandMessage
            {
                return CommandMessage.Deserialize(byt);
            }
            else if (bytes[0] == 1)//ChatMessage
            {
                return ChatMessage.Deserialize(byt);
            }
            return null;
        }
    }

    [Serializable]
    public class CommandMessage : IMessage
    {
        public int Sender { get; set; }
        public int Receiver { get; set; }
        public MessageType Type { get; set; }
        public object Data { get; set; }
        public int Status { get; set; }
        public ContentType Ctype { get; set; }
        public byte[] Serialize(bool tag = true)
        {
            var json = JsonConvert.SerializeObject(this);
            var byt = Encoding.UTF8.GetBytes(json);
            if (tag)
            {
                byte[] bytes = new byte[byt.Length + 1];
                bytes[0] = 0;
                byt.CopyTo(bytes, 1);
                return bytes;
            }
            return byt;
        }

        public string SerializeJson()
        {
            return JsonConvert.SerializeObject(this);
        }

        public static CommandMessage Deserialize(string msg)
        {
            return JsonConvert.DeserializeObject<CommandMessage>(msg);
        }

        public static CommandMessage Deserialize(byte[] bytes)
        {
            if (bytes == null)
                return null;
            var json = Encoding.UTF8.GetString(bytes);
            return JsonConvert.DeserializeObject<CommandMessage>(json);
        }

        public static CommandMessage Deserialize(byte[] bytes, int index, int count)
        {
            if (bytes == null)
                return null;
            var json = Encoding.UTF8.GetString(bytes, index, count);
            return JsonConvert.DeserializeObject<CommandMessage>(json);
        }

        public IMessage ChangeMsg()
        {
            return new ChatMessage()
            {
                Data = Data,
                Receiver = Receiver,
                Sender = Sender,
                Status = Status,
                Ctype = Ctype,
                Type = Type
            };
        }
    }

    [Serializable]
    public class ChatMessage : IMessage
    {

        public int Sender { get; set; }
        public int Receiver { get; set; }
        public MessageType Type { get; set; }
        public object Data { get; set; }
        public int Status { get; set; }
        public ContentType Ctype { get; set; }

        public IMessage ChangeMsg()
        {
            return new CommandMessage()
            {
                Data = Data,
                Receiver = Receiver,
                Sender = Sender,
                Status = Status,
                Type = Type,
                Ctype = Ctype
            };
        }

        public byte[] Serialize(bool tag = true)
        {
            MemoryStream ms = new MemoryStream();
            BinaryFormatter formatter = new BinaryFormatter();
            formatter.Serialize(ms, this);
            ms.Position = 0;
            byte[] byt = new byte[ms.Length];
            ms.Read(byt, 0, byt.Length);
            ms.Close();
            if (tag)
            {
                byte[] bytes = new byte[byt.Length + 1];
                bytes[0] = 1;
                byt.CopyTo(bytes, 1);
                return bytes;
            }
            return byt;
        }

        public static ChatMessage Deserialize(byte[] bytes)
        {
            if (bytes == null)
                return null;
            MemoryStream ms = new MemoryStream(bytes);
            ms.Position = 0;
            BinaryFormatter formatter = new BinaryFormatter();
            var obj = formatter.Deserialize(ms) as ChatMessage;
            ms.Close();
            return obj;
        }

        public static ChatMessage Deserialize(byte[] bytes, int index, int count)
        {
            if (bytes == null)
                return null;
            MemoryStream ms = new MemoryStream(bytes, index, count);
            ms.Position = 0;
            BinaryFormatter formatter = new BinaryFormatter();
            var obj = formatter.Deserialize(ms) as ChatMessage;
            ms.Close();
            return obj;
        }

        public string SerializeJson()
        {
            throw new NotImplementedException();
        }
    }
    public enum MessageType
    {
        Online,
        Offline,
        Chat,
        GroupChat,
        Broadcast,
        Friend,
        Ping
    }

    public enum ContentType
    {
        Normal,
        Image,
        Emoji,
        Costom,
        File,
        Link,
        Mix
    }
}
